package birdsong.client;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.LinkedList;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import birdsong.comm.ClientComm;
import birdsong.dummy.ClientCommDummy;

public class ClientGUI implements BirdsongClient {

	private JFrame janela;
	private Container contentor;
	private JLabel listaUtilizadores;
	private JPanel mensagens;
	private JList lista;
	private DefaultListModel modelo;
	private JScrollPane scroll;
	private JTextArea listaMensagens;
	private JTextField mostrador;
	private JButton enviarSMS, seguir, deixarSeguir, sair, entrar;
	private Container contentorEscrever, contentorUtilizadores;
	private ClientComm clienteCom;
	private String nome;
	private LinkedList<String> listaFollowed;
	private LinkedList<String> listaFollowing;
	private LinkedList<String> listaConectados;
//	private teste t;

	public ClientGUI() {
		listaFollowed = new LinkedList<String>();
		listaFollowing = new LinkedList<String>();
		listaConectados = new LinkedList<String>();

		janela = new JFrame();
		contentor = janela.getContentPane();
		contentor.setLayout(new BorderLayout());

		// criaçao da lista de utilizadores
		listaUtilizadores = new JLabel();
		contentorUtilizadores = new JPanel();
		modelo = new DefaultListModel();

		actualizarListas();

		lista = new JList(modelo);
		scroll = new JScrollPane(lista);
		contentorUtilizadores.setLayout(new BorderLayout());
		contentorUtilizadores.add(scroll, BorderLayout.CENTER);
		seguir = new JButton("Follow");

		seguir.addActionListener(new SentinelaSeguir());

		deixarSeguir = new JButton("Unfollow");
		deixarSeguir.addActionListener(new SentinelaDeixarSeguir());

		JPanel c = new JPanel();
		c.setLayout(new GridLayout(1, 3));
		c.add(seguir);
		c.add(deixarSeguir);
		contentorUtilizadores.add(c, BorderLayout.SOUTH);
		contentor.add(contentorUtilizadores, BorderLayout.WEST);

		// criaçao da lista de mensagens
		listaMensagens = new JTextArea();
		// listaMensagens.append("\n estamos malucas");
		// listaMensagens.append("\n nao nao estamos");

		contentor.add(listaMensagens, BorderLayout.CENTER);

		// criaçao de onde o utilizadores escreve mensagem
		contentorEscrever = new JPanel();
		contentorEscrever.setLayout(new BorderLayout());
		// int tamanhoMostrador = janela.getWidth()/2;
		mostrador = new JTextField();
		Container botoes = new Container();
		botoes.setLayout(new GridLayout(1, 2));
		contentorEscrever.add(mostrador, BorderLayout.CENTER);
		enviarSMS = new JButton("Send message");
		sair = new JButton("Disconect");
		entrar = new JButton("Connect");

		// envia o texto que cliente escreveu para o servidor
		enviarSMS.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (!mostrador.getText().equals("") && clienteCom.isConnected()) {
					System.out.println("mensagem enviada");
					clienteCom.sendBirdsongMessage(mostrador.getText());
					adicionaNovaMensagem(nome, mostrador.getText());
					mostrador.setText("");
					JOptionPane.showMessageDialog(null, "Message send!!!!");
				} else
					JOptionPane.showMessageDialog(null,
							"Erro: can not send message!!");
			}
		});

		sair.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (clienteCom.isConnected()) {
					clienteCom.disconnect();
					listaConectados.clear();
					listaFollowed.clear();
					listaFollowing.clear();
					actualizarListas();
					JOptionPane.showMessageDialog(null,
							"You are disconneted!!!!");
				} else
					JOptionPane.showMessageDialog(null,
							"You are already disconneted!!!!");

				// t.interrupt();
				// try {
				// t.join();
				// } catch (InterruptedException e) {
				// JOptionPane.showMessageDialog(null,
				// "Erro : Nao consegui terminar a thred!!!!");
				// e.printStackTrace();
				// }
			}
		});

		entrar.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.out.println(" antes do if " + clienteCom.isConnected());
				if (!clienteCom.isConnected()) {
					try {
						clienteCom = new ClientCommDummy();
						System.out.println(" seguir new cliente comm "
								+ clienteCom.isConnected());

						ligacaoServidor();
						System.out.println(clienteCom.isConnected());

					} catch (UnknownHostException e) {
						JOptionPane.showMessageDialog(null,
								"Servidor desconhecido!!!!");
					} catch (IOException e) {
						JOptionPane.showMessageDialog(null,
								"Não foi possível ligar ao servidor!!!!");
					}
					JOptionPane.showMessageDialog(null, "You are conneted!!!!");
				} else
					JOptionPane.showMessageDialog(null,
							"You are already conneted!!!!");
			}
		});

		botoes.add(enviarSMS);
		botoes.add(sair);
		botoes.add(entrar);
		contentorEscrever.add(botoes, BorderLayout.EAST);
		contentor.add(contentorEscrever, BorderLayout.SOUTH);

		nome = JOptionPane.showInputDialog("Qual o seu nickname?");
		janela.setTitle("Follow Me - " + nome);

		janela.setLocation(150, 100);
		janela.setSize(500, 400);
		janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args) {
		new ClientGUI().start(new ClientCommDummy());
	}

	/**
	 * 
	 * Faz a liagação ao servidor e apresenta a janela.
	 * 
	 * @throws UnknownHostException
	 *             Se nao conseguir encontrar o servidor.
	 * @throws IOException
	 *             Se não consegue estabeler a ligação.
	 */
	private void init() {
		try {
			ligacaoServidor();
			janela.setVisible(true);
		} catch (UnknownHostException e) {
			JOptionPane.showMessageDialog(null, "Servidor desconhecido!!!!");
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null,
					"Não foi possível ligar ao servidor!!!!");
		}
	}

	private void ligacaoServidor() throws IOException, UnknownHostException {
		clienteCom.connect("localhost", this.nome);
	}

	/**
	 * Lança o cliente e só retorna quando o cliente para.
	 * 
	 * @param clientComm
	 *            o clientComm é o meio pelo qual o cliente comunica com o
	 *            servidor.
	 */
	public void start(ClientComm cm) {
		this.clienteCom = (ClientCommDummy) cm;
		init();
//		t = new teste(clienteCom, this);
//		t.start();
	}

	/**
	 * Coloca nova menagem na lista de mensagens.
	 * 
	 * @param sendersNickname
	 *            o nickname do cliente que enviou a mensagem.
	 * @param payload
	 *            o payload é a mensagem que o cliente enviou.
	 */
	public void adicionaNovaMensagem(String sendersNickname, String payload) {
		listaMensagens.append("\n\n" + sendersNickname.toUpperCase() + ":");
		listaMensagens.append("\n" + payload);

	}

	/**
	 * Adiciona um cliente a lista de conectados.
	 * 
	 * @param cliente
	 *            o nickname do cliente que se conectou.
	 */
	public void adicionarClienteConetado(String cliente) {

		System.out.println("do Cliente :" + cliente);
		if (!listaConectados.contains(cliente)
				|| !listaFollowed.contains(cliente)
				|| !listaFollowing.contains(cliente)) {
			listaConectados.add(cliente);
		}
		actualizarListas();
	}

	/**
	 * Remove das listas cliente que já nao se encontra conectado.
	 * 
	 * @param ciente
	 *            o nickname do cliente que já nao se encontra conectado.
	 */
	public void removeUtilizador(String cliente) {
		actualizarListas();
		listaConectados.remove(cliente);
		listaFollowed.remove(cliente);
		listaFollowing.remove(cliente);
		actualizarListas();
	}

	/**
	 * Actualiza a lista de utilizadores, aparecendo em preimeiro lugar os
	 * followed, seguido pelos following e por fim os outros utilizasores
	 * conectados.
	 * 
	 */
	public void actualizarListas() {
		modelo.clear();

		modelo.addElement("Followed");

		for (String s : listaFollowed) {
			modelo.addElement(s);

		}
		modelo.addElement("Following");

		for (String a : listaFollowing) {
			modelo.addElement(a);

		}
		modelo.addElement("Other users");

		for (String b : listaConectados) {
			modelo.addElement(b);

		}
	}

	/**
	 * Adiciona na listaFollowing uma cliente.
	 * 
	 * @param cliente
	 *            nickname do cliente que veria ser adicionado.
	 */
	public void adicionaFollowed(String cliente) {
		if (!listaFollowed.contains(cliente)) {
			listaFollowed.add(cliente);
			listaConectados.remove(cliente);
		}
		actualizarListas();
	}

	/**
	 * Retira da listaFollowing um cliente
	 * 
	 * @param cliente
	 *            nickname do cliente que veria ser removido.
	 */
	public void removeFollowed(String cliente) {

		if (listaFollowed.contains(cliente)) {
			listaFollowed.remove(cliente);
			listaConectados.add(cliente);
			actualizarListas();

		}
		actualizarListas();
	}

	public class SentinelaDeixarSeguir implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			if (modelo.isEmpty()) {
				JOptionPane.showMessageDialog(janela,
						"Erro - Lista esta vazia!!");
			} else if (lista.getSelectedIndex() < 0) {
				JOptionPane.showMessageDialog(janela,
						"Erro - Não tem nenhuma opção selecionada!");
			} else if ((String) modelo.getElementAt(lista.getSelectedIndex()) == "Followed"
					|| (String) modelo.getElementAt(lista.getSelectedIndex()) == "Following"
					|| (String) modelo.getElementAt(lista.getSelectedIndex()) == "Other users") {
				JOptionPane.showMessageDialog(janela,
						"Erro - Não tem nenhuma opção certa selecionada!");
			} else {
				String unfollowed = (String) modelo.getElementAt(lista
						.getSelectedIndex());

				if (listaFollowing.contains(unfollowed)) {
					listaFollowing.remove(unfollowed);
					listaConectados.add(unfollowed);
					JOptionPane.showMessageDialog(janela, "Unfollow user - "
							+ unfollowed);
					clienteCom.unfollow(unfollowed);
					System.out.println("Chega aqui!!!!!!!!!!!!!");
				} else {
					JOptionPane.showMessageDialog(janela,
							"Nao esta a seguir o utilizador " + unfollowed);

				}
			}
			actualizarListas();
		}

	}

	public class SentinelaSeguir implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {

			if (modelo.isEmpty()) {
				JOptionPane.showMessageDialog(janela,
						"Erro - Lista esta vazia!!");
			} else if (lista.getSelectedIndex() < 0) {
				JOptionPane.showMessageDialog(janela,
						"Erro - Não tem nenhuma opção selecionada!");
			} else if ((String) modelo.getElementAt(lista.getSelectedIndex()) == "Followed"
					|| (String) modelo.getElementAt(lista.getSelectedIndex()) == "Following"
					|| (String) modelo.getElementAt(lista.getSelectedIndex()) == "Other users") {
				JOptionPane.showMessageDialog(janela,
						"Erro - Não tem nenhuma opção certa selecionada!");
			} else {
				String followed = (String) modelo.getElementAt(lista
						.getSelectedIndex());
				if (!listaFollowing.contains(followed)) {
					listaFollowing.add(followed);
					listaConectados.remove(followed);
					JOptionPane.showMessageDialog(janela, "Follow user - "
							+ followed);
					clienteCom.follow(followed);
				} else {
					JOptionPane.showMessageDialog(janela,
							"Já esta a seguir o utilizador " + followed);

				}
			}
			actualizarListas();
		}
	}

	public JTextArea getListaMensagens() {
		return listaMensagens;
	}

	public LinkedList<String> getListaFollowed() {
		return listaFollowed;
	}

	public LinkedList<String> getListaFollowing() {
		return listaFollowing;
	}

	public LinkedList<String> getListaConectados() {
		return listaConectados;
	}

}